from Foundation import *
from AppKit import *
import NSColorExt
import NSImageExt
from DBPath import DBPath

class DBFrame:

    clearImage =  None

    def __init__(self, lines=None):
 #       self.saveState = ['frame()']
        self.path = None
        self.paths = []
        self.undoStack = []
        self.lastPoint = None
        self._document = None
        if lines: 
            # restore from saved state
            for line in lines:
                for segment in line.split(','):
               # Move this to DBPath.pathFromString
                   if not segment: continue
                   method, x, y = segment.split()
                   if method == 'C':
                       self.path = DBPath(NSColor.colorFromString_(x),int(y)) # x is color, y is width
                       self.paths.append(self.path)
                   elif method == 'M':
                       point = int(x), int(y)
                       self.path.moveToPoint_(point)
                       self.lastPoint = point
                   elif method == 'L':
                       point = int(x), int(y)
                       self.path.lineToPoint_(point)
                       self.lastPoint = point
                   elif method == 'F':
                       self.path.drawFilled = True
                   else:
                        'Error in DBFrame.init(): restoring from unknown save state: '
                       
    def drawRect_(self, rect):
        for path in self.paths:
            path.draw()
            
    def drawRect_withAlpha_(self, rect, alpha):
        for path in self.paths:
            path.drawWithAlpha_(alpha)

    def copy(self):
        newFrame = DBFrame()
        newFrame.paths = [path.copyWithColor() for path in self.paths]
        newFrame.undoStack = [path.copyWithColor() for path in self.undoStack]
        newFrame.lastPoint = self.lastPoint
        newFrame._document = self._document
        return newFrame
        
    def document(self):
        if not self._document:
            self._document = NSDocumentController.sharedDocumentController().currentDocument()
        return self._document
        
    def pencolor(self):
        return self.document().pencolor()
        
    def penwidth(self):
        return self.document().penwidth()
        
    def undoLine(self, canvas):
        'Move a full line to the undo stack'
        if self.paths:
            self.undoStack.append(self.paths.pop())
        if self.paths:
            self.path = self.paths[-1]
        self.lastPoint = self.path.currentPoint()
        canvas.setNeedsDisplay_(True)
            
    def undoSegment(self, canvas):
        'Move a single lineto: to the undo stack'
        
    def redoLine(self, canvas):
        'Move a full line back from the redo stack'
        if self.undoStack:
            self.paths.append(self.undoStack.pop())
        self.path = self.paths[-1]
        self.lastPoint = self.path.currentPoint()
        self.path.stroke()
        canvas.setNeedsDisplay_(True)
        
    def redoSegment(self, canvas):
        'Move a single line segment back from the redo stack'

    def _rectFromPoints(self, pt1, pt2):
        x1, x2 = min(pt1[0], pt2[0]), max(pt1[0], pt2[0])
        y1, y2 = min(pt1[1], pt2[1]), max(pt1[1], pt2[1])
        w, h = x2 - x1, y2 - y1
        d = self.penwidth() * -0.5
        return NSInsetRect(NSMakeRect(x1, y1, w, h), d, d)
    
    def moveTo(self, point, fill=False):
        #if self.path:
        #    self.path.moveToPoint_(point)
        self.undoStack = []
        self.path = DBPath(self.pencolor(), self.penwidth(), point, fill=fill)
        self.paths.append(self.path)
        self.lastPoint = point
        
    def lineTo(self, point, canvas):
        if not self.path or self.path.lineColor() != self.pencolor() or self.path.lineWidth() != self.penwidth():
            self.undoStack = []
            self.path = DBPath(self.pencolor(), self.penwidth(), self.lastPoint, point)
            self.paths.append(self.path)
        else:
            self.path.lineToPoint_(point)
        if self.path.drawFilled:
            canvas.setNeedsDisplayInRect_(self.path.bounds())
        else:
            canvas.setNeedsDisplayInRect_(self._rectFromPoints(self.lastPoint, point))
        self.lastPoint = point

    def drawnBounds(self):
        if self.paths:
            return reduce(NSUnionRect, [p.bounds() for p in self.paths])
        else:
            return (0,0),(0,0)
        
    def translateXBy_yBy_(self, x, y):
        for path in self.paths:
            path.translateXBy_yBy_(x,y)
            
    def scaleXBy_yBy_(self, xScale, yScale):
        for path in self.paths:
            path.scaleXBy_yBy_(xScale, yScale)  
        
    def rotateByDegrees_(self, angleDegrees):
        for path in self.paths:
            path.rotateByDegrees_(angleDegrees)
                    
    def lastPenColor(self):
        if self.paths:
            return self.paths[-1].lineColor()
        else:
            return None
        
    def lastPenWidth(self):
        if self.paths:
            return self.paths[-1].lineWidth()
        else:
            return None
        
    def frameData(self):
        return 'frame(%s)' % ', '.join([path.asString() for path in self.paths])
        
    def frameDataAsSvg(self, height, index):
        return '<svg id="frame%05d">%s</svg>' % (index, ''.join([path.asSvg(height) for path in self.paths]))
        
    # 
    #  User Interface Validation
    #
    
    def canUndoLine(self):
        return len(self.paths) > 0
        
    def canRedoLine(self):
        return len(self.undoStack) > 0
